#ifndef __SPR_LOG_H__
#define __SPR_LOG_H__

#include <stdarg.h>
#include <stdint.h>
#include <semaphore.h>

class SprLog
{
public:
    ~SprLog();

    /**
     * @brief Get the Instance object
     *
     * @return SprLog*
     */
    static SprLog* GetInstance();

    // ----------------------------------------------------------------------------------------------------------------
    // - External interfaces for printing logs
    // ----------------------------------------------------------------------------------------------------------------
    int32_t d(const char* tag, const char* fileName, int lineNumber, const char* format, ...);
    int32_t i(const char* tag, const char* fileName, int lineNumber, const char* format, ...);
    int32_t w(const char* tag, const char* fileName, int lineNumber, const char* format, ...);
    int32_t e(const char* tag, const char* fileName, int lineNumber, const char* format, ...);

private:
    SprLog();

    /**
     * @brief LogImpl
     *
     * @param level     log level
     * @param tag       Tag of logs
     * @param format    Format of the output logs string
     * @param args      Variable parameters
     * @return          0 on success, or -1 if an error occurred
     *
     * The interface for printing logs can be connected to other log interfaces
     */
    int32_t LogImpl(const char* level, const char* tag, const char* fileName, int lineNumber, const char* format, va_list args);

    /**
     * @brief Writes a log string into shared memory.
     * @param logs      The log data to be stored.
     * @return          -1 if an error occurred,
     *                  Otherwise, returns the number of bytes written.
     */
    int32_t LogsToMemory(const char* logs, int32_t len);

private:
    sem_t* mWriteSem;
};

// --------------------------------------------------------------------------------------------------------------------
// - Log interface macro
// --------------------------------------------------------------------------------------------------------------------
#define LOGD(tag, fmt, args...)     SprLog::GetInstance()->d(tag, __FILE__, __LINE__, fmt, ##args)
#define LOGI(tag, fmt, args...)     SprLog::GetInstance()->i(tag, __FILE__, __LINE__, fmt, ##args)
#define LOGW(tag, fmt, args...)     SprLog::GetInstance()->w(tag, __FILE__, __LINE__, fmt, ##args)
#define LOGE(tag, fmt, args...)     SprLog::GetInstance()->e(tag, __FILE__, __LINE__, fmt, ##args)

#endif // __SPR_LOG_H__
